package net.yla.smartbus.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.yla.smartbus.core.api.RequestCode;
import net.yla.smartbus.core.exception.AppException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;


/**
 * @author Handy Wong
 * @date 2019/12/13 15:40
 * 生成指令推送接口URL工具类
 */
@Component
public class CreateUrl {
    @Value("${dataServiceUrl}")
    private String dataServiceUrl;
    @Value("${dataServicePoint}")
    private String dataServicePoint;
    //nginx代理地址
    @Value("${nginx.path}")
    private String nginxUrl;


    /**
     * @param service    请求业务
     * @param action     请求动作
     * @param formObject 请求动作
     * @return
     */
    public String getUrl(String service, String action, Object formObject) {
        String url = this.dataServiceUrl + ":" + this.dataServicePoint + "/" + service + "?action=" + action;
        //传过来的表单对象,通过反射获取其属性
        Class cla = formObject.getClass();
        //创建StringBuffer
        StringBuffer sb = new StringBuffer();
        //获取其所有属性
        Field[] fields = cla.getDeclaredFields();
        if (null != fields) {
            for (Field field : fields) {
                //打开私有访问
                field.setAccessible(true);
                try {
                    if (null != field.get(formObject)) {
                        //拿到属性名
                        String fieldName = field.getName();
                        //拿属性对应的值
                        String value = field.get(formObject).toString();
                        sb.append("&" + fieldName + "=" + value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        return url + sb.toString();
    }

    //发送Get请求
    public static JSONObject doGet(String httpUrl) {
        //定义一个链接对象
        HttpURLConnection conn = null;
        //定义一个字节输入流对象
        InputStream is = null;
        //字符输出流对象
        InputStreamReader isr = null;
        //缓冲流对象
        BufferedReader br = null;
        //sb对象
        StringBuilder result = new StringBuilder();
        //JSON对象
        JSONObject jsonObject = null;
        //定义远程url连接对象
        URL url = null;
        try {
            url = new URL(httpUrl);
            //通过远程url连接对象打开一个连接，强转成HTTPURLConnection类
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            //设置连接超时时间和读取超时时间
            conn.setConnectTimeout(15000);
            conn.setReadTimeout(60000);
            conn.setRequestProperty("Accept", "application/json");
            //发送请求
            conn.connect();
            //通过conn取得输入流，并使用Reader读取
            if (conn.getResponseCode() == 200) {//200指令执行成功
                //从链接对象中获取输入流对象
                is = conn.getInputStream();
                //将字节流转换为字符流
                isr = new InputStreamReader(is, "UTF-8");
                //创建缓冲流
                br = new BufferedReader(isr);
                String line;
                while ((line = br.readLine()) != null) {
                    result.append(line);
                }
                //响应结果转换成JSON对象
                jsonObject = (JSONObject) JSON.parse(result.toString());
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流对象
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != isr) {
                try {
                    isr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return jsonObject;

    }

    public void down(String httpUrl, HttpServletResponse response, String fileName, String fileType) {
        OutputStream os = null;
        //定义一个链接对象
        HttpURLConnection conn = null;
        //定义一个字节输入流对象
        InputStream is = null;
        //定义远程url连接对象
        URL url;
        try {
            url = new URL(this.nginxUrl + httpUrl);
            //通过远程url连接对象打开一个连接，强转成HTTPURLConnection类
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            //设置连接超时时间和读取超时时间
            conn.setConnectTimeout(15000);
            conn.setReadTimeout(60000);
            conn.setRequestProperty("Accept", "application/json");
            //发送请求
            conn.connect();
            response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + fileType, "UTF-8"));
            //通过conn取得输入流，
            if (conn.getResponseCode() == 200) {//200指令执行成功
                //从链接对象中获取输入流对象
                is = conn.getInputStream();
                os = response.getOutputStream();
                byte[] buffer = new byte[1024];
                int l;
                while ((l = is.read(buffer, 0, buffer.length)) != -1) {
                    os.write(buffer, 0, l);
                }
            } else {
                throw new AppException("未找到资源", RequestCode.Operate_Tip);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != os) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static String post(String strURL, String params) {
        System.out.println(strURL);
        System.out.println(params);
        BufferedReader reader = null;
        try {
            URL url = new URL(strURL);// 创建连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setRequestMethod("POST"); // 设置请求方式
            // connection.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
            connection.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式
            connection.connect();
            //一定要用BufferedReader 来接收响应， 使用字节来接收响应的方法是接收不到内容的
            OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "GBK"); // utf-8编码
            out.append(params);
            out.flush();
            out.close();
            // 读取响应
            reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "GBK"));
            String line;
            String res = "";
            while ((line = reader.readLine()) != null) {
                res += line;
            }
            reader.close();
            System.out.println(res);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "error"; // 自定义错误信息
    }

    /**
     * @param array
     * @return
     * @author Handy Wong
     */
    static Integer[] sortByCocktail(Integer[] array) {//Java之鸡尾酒排序
        /**
         * 鸡尾酒排序实际上是冒泡排序的改良,因为每一轮能同时进行相邻两位从小到大和从大到小的比较,所以总共循环数组长度的1/2轮
         * 直到最后一轮把最小值放在最左边,最大值放在最右边,排序结束
         */
        for (int i = 0; i < array.length / 2; i++) {
            //正序,相邻两位按照从小到大一一比较交换数值
            for (int j = 0; j < array.length - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }//正序循环
            //反序,相邻两位按照从大到小一一比较交换数值
            for (int k = array.length - i - 1; k > i; k--) {
                if (array[k] < array[k - 1]) {
                    int temp = array[k];
                    array[k] = array[k - 1];
                    array[k - 1] = temp;
                }
            }//反序循环
        }//for
        return array;
    }

    /**
     * @param array
     * @return array
     * @author Handy Wong
     */
    static Integer[] sortByChoose(Integer[] array) {//Java之选择排序
        /**
         * 选择排序:每一次拿一个待选数与其后面剩余的整个数组里元素进行一一比较,选出最小值下标,交换数值,放到前面
         */
        for (int i = 0; i < array.length; i++) {
            //首先我假定最小值就是我自己,然后与我之后的元素一一进行比较,如果找到比我还小的,交换下标,每一次比较出一个最小值,保存其下标
            int minIndex = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[minIndex] > array[j]) {
                    minIndex = j;
                }
            }
            //如果比较出来的最小值的下标跟之前假想为最小值的下标不一样,说明之前假想的最小值并不是这一轮操作的最小值
            //所以进行交换数值
            if (i != minIndex) {
                int temp = array[i];
                array[i] = array[minIndex];
                array[minIndex] = temp;
            }
        }
        return array;
    }

    /**
     * 插入排序
     *
     * @param array
     * @return
     * @author Handy Wong
     */
    static Integer[] sortByInsertion(Integer[] array) {//Java之插入排序
        /**
         *插入排序:从数组的第二位数据,也就是索引为1的位置的数据开始,
         * 依次循环向它之前已经进行了排序的假想数组进行插入排序工作
         */
        for (int i = 1; i < array.length; i++) {
            //执行插入的数据,也就是拿来跟假想数组进行比较的数值
            int temp = array[i];
            //遍历假想被插入的数组是从后往前遍历,因为每一次插入完成,假想数组一定是按照从小到大已经排序好了,
            //如果拿来插入的数值比假想数组的最后一位,也就是最假想数组的最大值还大,说明该数值就应该在此位置
            // 不需要进行数据后移,插入数据的操作
            // 如果小于最大值,则需要进行假想数组的数组后移,
            // 插入进行比较的数据
            // ,继续循环比较知道把被比较的数据插入到比前一位数据大,
            // 比后一位数据小的位置
            for (int j = i - 1; j >= 0 && temp < array[j]; j--) {
                //首选将前面已经排序好的假想数组的当前为进行数组后移,然后再其之前的位置插入数值
                array[j + 1] = array[j];
                array[j] = temp;
            }
        }
        return array;
    }

    /**
     * @param array
     * @return
     * @author Handy Wong
     */
    static Integer[] sortByBubble(Integer[] array) {//Java之冒泡排序
        /**
         * 冒泡排序,两两相邻进行比较交换位置
         */
        for (int i = 0; i < array.length; i++) {
            for (int m = 0; m < array.length - i - 1; m++) {
                if (array[m] > array[m + 1]) {
                    int temp = array[m + 1];//预先存好,小的数值
                    //交换数值
                    array[m + 1] = array[m];
                    array[m] = temp;

                }
            }
        }
        return array;
    }




}
